﻿using log4net;
using RealTimeCharts.LineChart;
using RealTimeCharts.LineChart.common;
using RemoteData.common.converter;
using RemoteData.core;
using RemoteData.core.Listener;
using RemoteData.core.queue;
using RemoteData.model;
using RemoteData.view.setting;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Drawing;
using System.Net.Sockets;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;


namespace RemoteData
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        private ILog logger = null;



        private MainWindowViewModel windowViewModel;

        private bool bLoaded = false;

        public MainWindow()
        {
            InitializeComponent();
            logger = LogManager.GetLogger(typeof(MainWindow));

            this.Loaded += new RoutedEventHandler(Window_Loaded);
            this.Closing += new System.ComponentModel.CancelEventHandler(Window_Closing);

            this.menuGlobalSetting.Click += new RoutedEventHandler(GlobalSetting_Click);

            int rn = TW_App.Init();
            if(rn != 0 )
            {
                string errMsg = "程序初始化失败";
                logger.ErrorFormat(errMsg);
                MessageBox.Show(errMsg, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }

            windowViewModel = new MainWindowViewModel();
            this.DataContext = windowViewModel;

            DGWaveLenTable.SelectionMode = DataGridSelectionMode.Single;
            DGWaveLenTable.ItemsSource = windowViewModel.chDataItems;


            tableRefreshMsgWorker = CreateRefreshWorker();
            StartRefreshWorker();

            chSeriesColor = MakeLegendColorTable();

            InitChart();
        }


        #region 窗体事件
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            BuildTable(16, 8);
            bLoaded = true;

            this.canvas.SizeChanged += new SizeChangedEventHandler(Canvas_SizeChanged);

            CreateChart(false);
        }

        private void Canvas_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            CreateChart(false);
        }

        private void Window_Closing(object sender, CancelEventArgs e)
        {
            StopChartRefreshWorker();
            StopRefreshWorker();
            TW_App.ProgramQuit();
        }


        private void GlobalSetting_Click(object sender, RoutedEventArgs e)
        {
            GlobalSettingDlg dlg = new GlobalSettingDlg();
            dlg.Owner = this;
            dlg.WindowStartupLocation = WindowStartupLocation.CenterOwner;
            bool? result = dlg.ShowDialog();

            if (result == true)
            {
                int port = TW_App.globalSetting.listenerPort;
                if(port != TW_App.listenerManager.port)
                {
                    TW_App.StopListener();
                    try
                    {
                        UdpClient client = new UdpClient(TW_App.globalSetting.listenerPort);
                        client.Close();
                    }
                    catch(Exception)
                    {
                        MessageBox.Show("监听端口被占用", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                    }

                    StopChartRefreshWorker();
                    StopRefreshWorker();

                    TW_App.listenerManager = new ListenerManager(TW_App.globalSetting.listenerPort);
                    TW_App.StartListener();

                    StartChartRefreshWorker();
                    StartRefreshWorker();
                }
            }
        }
        #endregion


        #region 波长相关

        OPM_MsgWorker tableRefreshMsgWorker = null; // UDP
        private readonly object gsLocker = new object();
        private DateTime tm1 = DateTime.Now;
        private OPM_MsgWorker CreateRefreshWorker()
        {
            OPM_MsgWorker worker = new OPM_MsgWorker();
            worker.handleProc = TableDataRefreshProc;
            worker.keyList.Add(QueueDataType.DATA_WL);

            return worker;
        }

        private void StartRefreshWorker()
        {
            if (tableRefreshMsgWorker.IsStop())
            {
                tableRefreshMsgWorker.StartAsync();
                //currentDebugDeviceClient.Register(tableRefreshMsgWorker, new MsgDispatcherKey(MsgType.MSG_DATA_WL, null)); // TCP
                TW_App.listenerManager.Register(tableRefreshMsgWorker, QueueDataType.DATA_WL); // UDP
                //windowViewModel.startReceiving = true;
                logger.InfoFormat("波长Table更新线程启动");
            }
        }

        private void StopRefreshWorker()
        {
            if (!tableRefreshMsgWorker.IsStop())
            {
                tableRefreshMsgWorker.Stop();
                if (TW_App.listenerManager != null)
                {
                    //currentDebugDeviceClient.UnRegister(tableRefreshMsgWorker, new MsgDispatcherKey(MsgType.MSG_DATA_WL, null));  // TCP
                    TW_App.listenerManager.UnRegister(tableRefreshMsgWorker, QueueDataType.DATA_WL);  // UDP
                }

                //windowViewModel.startReceiving = false;
                logger.InfoFormat("波长Table更新线程结束");
            }

        }

        private void TableDataRefreshProc(QueueData msg) // UDP
        {

            //logger.Debug("refresh wavelen proc start");

            DateTime tm2 = DateTime.Now;
            TimeSpan ts = tm2 - tm1;

            int frequence = 10;
            int intervalTm = 1000 / frequence;

            if (ts.TotalMilliseconds > intervalTm)
            {
                tm1 = DateTime.Now;
                App.Current.Dispatcher.Invoke((Action)(() =>
                {
                    lock (gsLocker)
                    {
                        ShowData(msg);
                        logger.Debug("refresh wavelen finish");
                    }

                }));

            }

        }
        //private Wave lastWaveLenData = null;
        private void ShowData(QueueData msg) // UDP
        {
            if (!bLoaded) return;

            if (bLoaded)
            {
                logger.Debug("ShowData, bLoaded is true");
            }

            //if (msg.header.messsageType != MsgType.MSG_DATA_WL) // TCP
            if (msg.type != QueueDataType.DATA_WL) // UDP
            {
                //logger.ErrorFormat("收到不支持的消息类型({0:x8})", msg.header.messsageType); // TCP
                logger.ErrorFormat("收到不支持的消息类型({0:x8})", msg.type); // UDP
                return;
            }

            //os_acq_wl_data waveLenData = ((os_wl_data)msg).waveLenData; // TCP
            Wave waveLenData = (Wave)msg; // UDP

            //lastWaveLenData = waveLenData;


            if (waveLenData.nChannel > 0)
            {
                //windowViewModel.chDataItems.Clear();
                //for (int ch = 0; ch < waveLenData.nChannel; ch++)
                //{
                //    ChDataItemViewModel chDataItem = new ChDataItemViewModel();
                //    windowViewModel.chDataItems.Add(chDataItem);

                //    chDataItem.channelNo = ch + 1;
                //    chDataItem.waveLen = waveLenData.wave[ch].waveLen;
                //    chDataItem.ngratting = waveLenData.wave[ch].waveLen.Length;

                //    SetUpdateStatus(ref chDataItem, waveLenData.wave[ch].waveLen);
                //}


                //只有在通道数不同的情况下，再重新创建，避免频繁的刷新
                //WaveLenDisplaySettingViewModel settingViewModel = windowViewModel.settingViewModel.displaySetting;

                if (windowViewModel.chDataItems.Count != waveLenData.nChannel)
                {
                    windowViewModel.chDataItems.Clear();

                    for (int ch = 0; ch < waveLenData.nChannel; ch++)
                    {
                        // WaveLenDisplaySettingViewModel settingViewModel = windowViewModel.settingViewModel.displaySetting;
                        ChDataItemViewModel chDataItem = new ChDataItemViewModel(8);
                        windowViewModel.chDataItems.Add(chDataItem);
                    }
                }

                for (int ch = 0; ch < waveLenData.nChannel; ch++)
                {
                    if (waveLenData.chGratting[ch].ngrating == 0)
                    {
                        waveLenData.chGratting[ch].waveValueArray = new double[0]; // UDP
                        waveLenData.chGratting[ch].dBmValue = new double[0]
;
                    }

                    ChDataItemViewModel chDataItem = windowViewModel.chDataItems[ch];

                    chDataItem.channelNo = ch + 1;
                    /** TCP */
                    //chDataItem.waveLen = waveLenData.wave[ch].waveLen;
                    //chDataItem.ngratting = waveLenData.wave[ch].waveLen.Length;
                    //SetUpdateStatus(ref chDataItem, waveLenData.wave[ch].waveLen);

                    /** UDP */
                    chDataItem.waveLen = waveLenData.chGratting[ch].waveValueArray;

                    chDataItem.ngratting = waveLenData.chGratting[ch].waveValueArray.Length;
                    SetUpdateStatus(ref chDataItem, waveLenData.chGratting[ch].waveValueArray);
                }
            }

        }

        private void SetUpdateStatus(ref ChDataItemViewModel chData, double[] newValues)
        {
            //bool trigger = false;
            //double[] waveLen = chData.waveLen;
            //int channelNo = chData.channelNo;

            //for (int i = 0; i < waveLen.Length; i++)
            //{
            ////double diffValue = this.m_waveLen[i] - value[i];
            //if (windowViewModel.loadStdValue)
            //{
            //    double stdValue = windowViewModel.waveLenStdValue[channelNo - 1].waveLen[i];
            //    double diffValue = 0.0;
            //    if (newValues.Length > i)
            //    {
            //        if (!stdValue.Equals(double.NaN))
            //        {
            //            diffValue = newValues[i] - stdValue;
            //        }
            //        else
            //        {
            //            //没有标准值，出现了新的光栅
            //            diffValue = double.MaxValue; //设置成最大值
            //        }
            //    }
            //    else
            //    {
            //        //有标准值，但是当前的光栅已经消失
            //        if (!stdValue.Equals(double.NaN))
            //        {
            //            diffValue = double.MinValue; //设置成最小值
            //        }
            //    }

            //    double lowThreshold = windowViewModel.settingViewModel.displaySetting.lowWaveLenThreshold;
            //    double upThreshold = windowViewModel.settingViewModel.displaySetting.upWaveLenThreshold;

            //    if ((diffValue > 0 && diffValue > upThreshold) || (diffValue < 0 && diffValue < (0 - lowThreshold)))
            //    {
            //        //之前的状态不是1，需要刷新
            //        if (chData.updateStatus[i].status != 1)
            //        {
            //            trigger = true;
            //            chData.updateStatus[i].updateFlag = true;
            //            chData.updateStatus[i].status = 1;
            //        }
            //    }
            //    else
            //    {
            //        //之前的状态不是0，需要刷新
            //        if (chData.updateStatus[i].status != 0)
            //        {
            //            trigger = true;
            //chData.updateStatus[i].updateFlag = true;
            //chData.updateStatus[i].status = 0;
            //    }
            //}


            //}
            //}

            //if (trigger)
            //{
            //chData.updateTrigger = true;
            //}

            chData.cellBackColorParameter = string.Format("{0},{1},{2}", "#8B008B", "#FFf5f5f7", "#FFF0F8FF");
            chData.cellTextColorParameter = string.Format("{0},{1}", "#FFFFFF", "#000000");
        }

        private void BuildTable(int nChannel, int nGratting)
        {
            this.DGWaveLenTable.Columns.Clear();

            Style styleCenter = new Style(typeof(TextBlock));
            Setter horizonCenter = new Setter(TextBlock.HorizontalAlignmentProperty, HorizontalAlignment.Center);
            Setter verticalCenter = new Setter(TextBlock.VerticalAlignmentProperty, VerticalAlignment.Center);
            //    Setter bgSetter = new Setter(TextBlock.BackgroundProperty, new SolidColorBrush(Colors.Red));
            styleCenter.Setters.Add(horizonCenter);
            styleCenter.Setters.Add(verticalCenter);
            //    styleCenter.Setters.Add(bgSetter);

            //System.Windows.Controls.Primitives.DataGridColumnHeader header = new System.Windows.Controls.Primitives.DataGridColumnHeader();
            //Style headerStyle = new System.Windows.Style();
            //headerStyle.TargetType = header.GetType();
            //Setter setter = new Setter();
            //setter.Property = FontSizeProperty;
            //setter.Value = 20;
            //headerStyle.Setters.Add(setter);
            //  headerStyle.Setters.Add(widthStyle);

            DataGridTextColumn colChannel = new DataGridTextColumn();
            colChannel.Header = "通道";

            //   colChannel.HeaderStyle = headerStyle;
            //  colChannel.Width = new DataGridLength(1, DataGridLengthUnitType.Star);
            colChannel.ElementStyle = styleCenter;

            colChannel.Binding = new Binding()
            {
                //Background = 

                Path = new PropertyPath("channelNo"),
                Mode = BindingMode.TwoWay,
                // UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,

                NotifyOnSourceUpdated = true,
                NotifyOnTargetUpdated = true
            };
            this.DGWaveLenTable.Columns.Add(colChannel);

            for (int i = 0; i < nGratting; i++)
            {

                DataGridTextColumn sensorColumn = new DataGridTextColumn();
                sensorColumn.Header = "光栅" + (i + 1).ToString();


                string bindStr = string.Format("waveLen[{0}]", i);
                string converterStr = "0:0.0000";
                //               sensorColumn.Width = new DataGridLength(1, DataGridLengthUnitType.Star);
                sensorColumn.ElementStyle = styleCenter;
                sensorColumn.Binding = new Binding()
                {
                    Path = new PropertyPath(bindStr),
                    Mode = BindingMode.TwoWay,
                    Converter = new DoubleToStrConverter(),
                    ConverterParameter = converterStr,
                    //UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
                    NotifyOnSourceUpdated = true,
                    NotifyOnTargetUpdated = true

                };

                this.DGWaveLenTable.Columns.Add(sensorColumn);

            }

            //set CellStyle 背景
            Style cellStyle = new Style(typeof(DataGridCell));
            Setter bgSetter = new Setter(DataGridCell.BackgroundProperty, new System.Windows.Media.SolidColorBrush(System.Windows.Media.Colors.Red));

            cellStyle.Setters.Add(bgSetter);

            DataTrigger d = new DataTrigger();
            d.Binding = new Binding("status");
            d.Value = 1;


            //   this.DGWaveLenTable.CellStyle = cellStyle;
        }

        #endregion


        #region 光谱相关
        private readonly object gpLocker = new object(); //光谱图的locker

        OPM_MsgWorker chartRefreshMsgWorker = null; // UDP
        List<System.Drawing.Color> chSeriesColor;

        List<List<ValuePoint>> chartDatas = new List<List<ValuePoint>>();

        DateTime refreshTm1 = DateTime.Now;

        LineChart lineChart = null;

        private void InitChart()
        {
            chartRefreshMsgWorker = CreateChartRefreshWorker();
            for (int i = 0; i < 16; i++)
            {
                chartDatas.Add(new List<ValuePoint>());
            }
            StartChartRefreshWorker();
        }

        private OPM_MsgWorker CreateChartRefreshWorker()
        {
            OPM_MsgWorker worker = new OPM_MsgWorker();
            worker.handleProc = ChartDataRefreshProc;

            //List<int> channelNoList = new List<int>();
            //foreach (var v in windowViewModel.spectrumDisplayViewModel.selectedChannelItems)
            //{
            QueueDataType key = QueueDataType.DATA_SP;
            worker.keyList.Add(key);
            //}

            return worker;

        }
        private void StartChartRefreshWorker()
        {
            if (chartRefreshMsgWorker.IsStop())
            {
                chartRefreshMsgWorker.StartAsync();

                for(int i = 0;i< 16; i++)
                {
                    chartDatas[i].Clear();
                }
                List<QueueDataType> keyList = new List<QueueDataType>();
                QueueDataType key = QueueDataType.DATA_SP;
                keyList.Add(key);
                chartRefreshMsgWorker.keyList = keyList;
                TW_App.listenerManager.Register(chartRefreshMsgWorker, chartRefreshMsgWorker.keyList);

            }
        }

        private void StopChartRefreshWorker()
        {
            if (!chartRefreshMsgWorker.IsStop())
            {
                chartRefreshMsgWorker.Stop();

                List<QueueDataType> keyList = new List<QueueDataType>(); 

                QueueDataType key = QueueDataType.DATA_SP;
                keyList.Add(key);

                TW_App.listenerManager.UnRegister(chartRefreshMsgWorker, keyList);
                

                logger.InfoFormat("光谱图更新线程停止");
            }
        }

        private void ChartDataRefreshProc(QueueData msg) // UDP
        {
            lock (gsLocker)
            {
                SpectrumData spData = (SpectrumData)msg;

                int channelNo = spData.channelNo;

                windowViewModel.serialNo = spData.serialNo;
                windowViewModel.version = spData.version;
                windowViewModel.nChannel = spData.nChannel;
                windowViewModel.forwardVersion = spData.forwardVersion;
                windowViewModel.temperature = spData.temperature;
                windowViewModel.runTime = spData.runTime;

                chartDatas[channelNo].Clear();
                spData.ValuePoints.ForEach(x => chartDatas[channelNo].Add(new ValuePoint(x.valX,x.valY)));

                ShowData(chartDatas);

                App.Current.Dispatcher.InvokeAsync((Action)(() =>
                {
                    windowViewModel.spectrumDatas[channelNo].wds.Clear();
                    for (int i = 0; i < spData.dBmValue.Length; i++)
                    {
                        WdValueViewModel wd = new WdValueViewModel();
                        wd.dBm = spData.dBmValue[i];
                        wd.waveLen = spData.waveValueArray[i];
                        windowViewModel.spectrumDatas[channelNo].wds.Add(wd);
                    }
                }));
            }
        }


        private void CreateChart(bool reset)
        {
            int width = (int)canvas.ActualWidth;
            int height = (int)canvas.ActualHeight;

            if (width > 0 && height > 0)
            {
                spectrumImage.Width = width;
                spectrumImage.Height = height;
            }

            if (lineChart == null || reset)
            {
                Title chartTitle = new Title(new RealTimeCharts.LineChart.Padding(10, 10, 10, 5), "光谱图", new Font("Arial", 12, System.Drawing.FontStyle.Bold), new SolidBrush(System.Drawing.Color.Black));

                // y轴标签
                TitleProperty titlePropertyY = new TitleProperty();
                titlePropertyY.title = "强度(dBm)";
                titlePropertyY.titleTextFont = new Font("Arial", 10, System.Drawing.FontStyle.Bold);
                AxisTitle axisTitle = new AxisTitle(null, titlePropertyY, (int)Position.Left);

                AxisScaleWindow axisScaleWindow = new AxisScaleWindow();
                axisScaleWindow.scaleX.mode = SCALE_SHOW_MODE.Normal;

                axisScaleWindow.scaleX.valueRange.minValue = 1525;
                axisScaleWindow.scaleX.valueRange.maxValue = 1565;

                ScaleLineProperty linePropertyX = new ScaleLineProperty();
                linePropertyX.color = Color.LightGray;
                linePropertyX.width = 1;
                linePropertyX.type = LineType.LongDashed;
                axisScaleWindow.scaleX.lineProperty = linePropertyX;
                axisScaleWindow.scaleX.scaleTextFormat = "0:F3";

                axisScaleWindow.scaleY.mode = SCALE_SHOW_MODE.Normal;
                axisScaleWindow.scaleY.valueRange.minValue = -75;
                axisScaleWindow.scaleY.valueRange.maxValue = 0;
                ScaleLineProperty linePropertyY = new ScaleLineProperty();
                linePropertyY.color = Color.LightGray;
                linePropertyY.width = 1;
                linePropertyY.type = LineType.LongDashed;
                axisScaleWindow.scaleY.lineProperty = linePropertyY;

                axisScaleWindow.UpdateScaleValue();

                Pen borderPen = new Pen(Color.Black, 1);
                List<int> channelNoList = new List<int>();
                for(int i = 0; i < 16; i++)
                {
                    channelNoList.Add(i+1);
                }
                ColorLegend colorLegend = MakeLegend(channelNoList, new Font("Arial", 8), borderPen);

                lineChart = new LineChart(width, height, Color.Transparent, chartTitle, axisTitle, axisScaleWindow, colorLegend);

            }
            else
            {
                lineChart.ReSize(width, height);
            }

            spectrumImage.Source = lineChart.GetSource();

            lineChart.Clear();
            lineChart.Show(true);

        }

        private void ShowData(List<List<ValuePoint>> points)
        {
            //if (lineChart.elemList == null)
            //{
            //    lineChart.elemList = new List<List<ValuePoint>>();
            //}

            //lineChart.elemList.Clear();

            lineChart.elemList = points;

            App.Current.Dispatcher.InvokeAsync((Action)(() =>
            {
                lineChart.Show(true);
            }));
        }

        private ColorLegend MakeLegend(List<int> channelNoList, Font font, Pen borderPen)
        {
            List<ColorLegendData> colorLegendDataList = new List<ColorLegendData>();

            foreach (var v in channelNoList)
            {
                ColorLegendData newData = new ColorLegendData();
                newData.color = chSeriesColor[v - 1];
                newData.text = "通道" + v.ToString();
                colorLegendDataList.Add(newData);
            }

            ColorLegend colorLegend = new ColorLegend(colorLegendDataList, font, borderPen, Position.TopRight);
            return colorLegend;

        }
        private List<System.Drawing.Color> MakeLegendColorTable()
        {
            List<System.Drawing.Color> colorList = new List<System.Drawing.Color>();
            int r = 0, g = 0, b = 0;

            colorList.Add(System.Drawing.Color.FromArgb(0x00, 0x00, 0x00));

            colorList.Add(System.Drawing.Color.FromArgb(0xFF, 0x00, 0x00));
            colorList.Add(System.Drawing.Color.FromArgb(0x00, 0xFF, 0x00));
            colorList.Add(System.Drawing.Color.FromArgb(0x00, 0x00, 0xFF));

            colorList.Add(System.Drawing.Color.FromArgb(0xFF, 0xFF, 0x00));
            colorList.Add(System.Drawing.Color.FromArgb(0xFF, 0x00, 0xFF));
            colorList.Add(System.Drawing.Color.FromArgb(0x00, 0xFF, 0xFF));

            colorList.Add(System.Drawing.Color.FromArgb(0x80, 0x00, 0x00));
            colorList.Add(System.Drawing.Color.FromArgb(0x00, 0x80, 0x00));
            colorList.Add(System.Drawing.Color.FromArgb(0x00, 0x00, 0x80));

            colorList.Add(System.Drawing.Color.FromArgb(0x80, 0x80, 0x00));
            colorList.Add(System.Drawing.Color.FromArgb(0x80, 0x00, 0x80));
            colorList.Add(System.Drawing.Color.FromArgb(0x00, 0x80, 0x80));

            colorList.Add(System.Drawing.Color.FromArgb(0xFF, 0xB0, 0xB0));
            colorList.Add(System.Drawing.Color.FromArgb(0x80, 0x80, 0x80));
            colorList.Add(System.Drawing.Color.FromArgb(0xFF, 0x40, 0x40));

            colorList.Add(System.Drawing.Color.FromArgb(0xA0, 0x80, 0x20));
            colorList.Add(System.Drawing.Color.FromArgb(0x20, 0x80, 0x20));


            colorList.Add(System.Drawing.Color.FromArgb(0x32, 0xCD, 0x32));
            colorList.Add(System.Drawing.Color.FromArgb(0x48, 0xD1, 0xCC));
            colorList.Add(System.Drawing.Color.FromArgb(0x64, 0x95, 0xED));
            colorList.Add(System.Drawing.Color.FromArgb(0x41, 0x69, 0xE1));
            colorList.Add(System.Drawing.Color.FromArgb(0xEE, 0x82, 0xEE));
            colorList.Add(System.Drawing.Color.FromArgb(0x8A, 0x2B, 0xE2));
            colorList.Add(System.Drawing.Color.FromArgb(0xDB, 0x70, 0x93));
            colorList.Add(System.Drawing.Color.FromArgb(0xFF, 0xE4, 0xE1));
            colorList.Add(System.Drawing.Color.FromArgb(0x70, 0x80, 0x90));
            colorList.Add(System.Drawing.Color.FromArgb(0xD2, 0x69, 0x1E));
            colorList.Add(System.Drawing.Color.FromArgb(0xF0, 0x80, 0x80));
            colorList.Add(System.Drawing.Color.FromArgb(0xDC, 0x14, 0x3C));
            colorList.Add(System.Drawing.Color.FromArgb(0xFF, 0xD7, 0x00));
            colorList.Add(System.Drawing.Color.FromArgb(0xFF, 0xFA, 0xCD));

            return colorList;
        }
        #endregion
    }

    public class MainWindowViewModel : ViewModelBase
    {
        public MainWindowViewModel()
        {
            title = TW_App.TITLE + " v" + TW_App.VERSION;

            chDataItems = new ObservableCollection<ChDataItemViewModel>();

            spectrumDatas = new ObservableCollection<SpectrumDataViewModel>();
            for(int i = 0; i< 32; i++)
            {
                SpectrumDataViewModel sd = new SpectrumDataViewModel();
                sd.channelName = "通道" + (i + 1);
                spectrumDatas.Add(sd);
            }
        }

        private string m_title;
        public string title
        {
            get { return m_title; }
            set
            {
                m_title = value;
                NotifyPropertyChanged();
            }
        }

        private ObservableCollection<ChDataItemViewModel> m_chDataItems;
        public ObservableCollection<ChDataItemViewModel> chDataItems
        {
            get { return m_chDataItems; }
            set
            {
                this.m_chDataItems = value;
                NotifyPropertyChanged();
            }
        }

        private string m_serialNo;
        public string serialNo
        {
            get { return m_serialNo; }
            set
            {
                m_serialNo = value;
                NotifyPropertyChanged();
            }
        }

        private string m_version;
        public string version
        {
            get { return m_version; }
            set
            {
                m_version = value;
                NotifyPropertyChanged();
            }
        }

        private int m_nChannel;
        public int nChannel
        {
            get { return m_nChannel; }
            set
            {
                m_nChannel = value;
                NotifyPropertyChanged();
            }
        }

        private int m_forwardVersion;
        public int forwardVersion
        {
            get { return m_forwardVersion; }
            set
            {
                m_forwardVersion = value;
                NotifyPropertyChanged();
            }
        }

        private double m_temperature;
        public double temperature
        {
            get { return m_temperature; }
            set
            {
                m_temperature = value;
                NotifyPropertyChanged();
            }
        }

        private int m_runTime;
        public int runTime
        {
            get { return m_runTime; }
            set
            {
                m_runTime = value;
                NotifyPropertyChanged();
            }
        }

        private ObservableCollection<SpectrumDataViewModel> m_spectrumDatas;
        public ObservableCollection<SpectrumDataViewModel> spectrumDatas
        {
            get { return m_spectrumDatas; }
            set
            {
                m_spectrumDatas = value;
                NotifyPropertyChanged();
            }
        }
    }
}
